#include "GfxDriver/WGL/WGLRenderTarget.h"

#include "Core/Kernel.h"
#include "Core/LogService.h"

#include "GfxDriver/GfxDriver.h"
#include "GfxDriver/WGL/WGLRenderedTexture.h"
#include "GfxDriver/WGL/WGLDepthBuffer.h"

namespace Orca {

	//--------------------------------------------------------------------------
	WGLRenderTarget* WGLRenderTarget::create(GfxDriver *gfxDriver) {

		WGLRenderTarget* rt = new WGLRenderTarget;

		if( !rt->_init(gfxDriver) ) {

			delete rt;
			return NULL;
		}

		return rt;
	}

	//--------------------------------------------------------------------------
	bool WGLRenderTarget::_init(GfxDriver *gfxDriver) {

		mGfxDriver = gfxDriver;

		mGfxDriver->resetErrors();

		glGenFramebuffersEXT(1, &mGLHandle);

		if(GL_NO_ERROR != glGetError() ) {

			LOG_ERR("WGLRenderTarget::_init failed");
			return false;
		}

		return true;
	}
	
	//--------------------------------------------------------------------------
	WGLRenderTarget::WGLRenderTarget()
		: mGfxDriver(NULL)
		, mGLHandle(0)
		, mDirty(false)
		, mHasColorTarget(false) {

		for(uint32 i=0; i<MAX_COLOR_TARGET; ++i)
			mColorTarget[i] = NULL;

		mDepthTarget = NULL;
	}

	//--------------------------------------------------------------------------
	WGLRenderTarget::~WGLRenderTarget() {

		if(mGLHandle)
			glDeleteFramebuffersEXT(1, &mGLHandle);
	}

	//--------------------------------------------------------------------------
	uint32 WGLRenderTarget::getMaxColorTarget() {

		return MAX_COLOR_TARGET;
	}

	//--------------------------------------------------------------------------
	bool WGLRenderTarget::makeCurrent() {

		if(!mHasColorTarget)
			return false;

		glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, mGLHandle);

		if(mDirty) {

			for(uint32 i=0; i<MAX_COLOR_TARGET; ++i) {

				GLuint texId = 0;
				if(mColorTarget[i]) texId = mColorTarget[i]->getAPIHandle();

				glFramebufferTexture2DEXT(
					GL_FRAMEBUFFER_EXT,
					(GLenum)GL_COLOR_ATTACHMENT0_EXT + i,
					GL_TEXTURE_2D,
					texId,
					0);
			}

			GLuint depthBufId = 0;
			if(mDepthTarget) depthBufId = mDepthTarget->getAPIHandle();

			glFramebufferRenderbufferEXT(
				GL_FRAMEBUFFER_EXT,
				GL_DEPTH_ATTACHMENT_EXT,
				GL_RENDERBUFFER_EXT, depthBufId);

			mDirty = false;
		}

		GLenum fboStatus = glCheckFramebufferStatusEXT(GL_FRAMEBUFFER_EXT);

		if(fboStatus != GL_FRAMEBUFFER_COMPLETE_EXT)
			return false;

		return true;
	}

	//--------------------------------------------------------------------------
	bool WGLRenderTarget::bindColorTarget(uint32 channel, TextureRendered *target) {

		if(channel >= MAX_COLOR_TARGET)
			return false;

		mColorTarget[channel]	= target;
		mHasColorTarget			= (mColorTarget[channel] != NULL);
		mDirty					= true;

		return true;
	}

	//--------------------------------------------------------------------------
	bool WGLRenderTarget::bindDepthTarget(DepthBuffer *target) {

		mDepthTarget	= target;
		mDirty			= true;

		return true;
	}

	//--------------------------------------------------------------------------
}